package elevator;

import java.util.Stack;
import java.util.Vector;

public class ElvAlg {
	private boolean goingUp = true;
	private Vector<Integer> upStops;
	private Stack<Integer> nextUp;
	private Vector<Integer> downStops;
	private Stack<Integer> nextDown;
	private int currentFloor = 0;
	private int moving = 0;//1=up,0=idle,-1=down
	/**
	 * constructor
	 */
	public ElvAlg(){
		upStops = new Vector<Integer>();
		downStops = new Vector<Integer>();
		nextUp = new Stack<Integer>();
		nextDown = new Stack<Integer>();
	}
	/**
	 * floor number pressed from inside the elevator
	 * does not care if the elevator is currently going up or down
	 * @param i:floor number
	 */
	public void floorPressed(int floor){
		if(floor == currentFloor){
			System.out.println("why do you derp?");
		}
		else{
			if(floor < currentFloor){
				if(isIdle()){
					goingUp = false;
				}
				addDown(floor);
			}else{
				if(isIdle()){
					goingUp = true;
				}
				addUp(floor);
			}
		}
		
	}
	/**
	 * the floor it stops on
	 * @param floor
	 */
	public void stops(Integer floor){
		currentFloor =floor;
		if(goingUp){
			if(upStops.contains(floor)){
				upStops.remove(floor);
			}
			else{
				System.out.println("skomt");
			}
			if(nextDown.contains(floor))
				nextDown.remove(floor);
			if(upStops.isEmpty()){
				goingUp = false;
				while(!nextDown.isEmpty()){
					addDown(nextDown.pop());
				}
				if(downStops.isEmpty()){
					goingUp = true;
					while(!nextUp.isEmpty())
						addUp(nextUp.pop());

				}
			}
		}else{
			if(downStops.contains(floor)){
				downStops.remove(floor);
			}
			else{
				System.out.println("skomt2");
			}
			if(nextUp.contains(floor))
				nextUp.remove(floor);
			if(downStops.isEmpty()){
				goingUp = true;
				while(!nextUp.isEmpty())
					addUp(nextUp.pop());
				if(upStops.isEmpty())
					goingUp = false;
				while(!nextDown.isEmpty())
					addDown(nextDown.pop());
			}
		}
	}
	/**
	 * if the elevator is called
	 * @param i:the floor its called to
	 * @param up:if the person calling the elevator want to go up.
	 */
	public void call(int floor, boolean up){
		
		if(isIdle()){
			if(up){
				upStops.add(floor);
				goingUp = true;
			}else{
				downStops.add(floor);
				goingUp = false;
			}
			if(floor < currentFloor)
				moving = -1;
			else
				moving = 1;
		}else{
			if(up){
				if(moving == 1 && currentFloor >= floor){
					if(!nextUp.contains(floor))
						nextUp.add(floor);
				}
				else if(moving==-1&&currentFloor<=floor){
					if(!nextUp.contains(floor))
						nextUp.add(floor);
				}
				else{
					if(!upStops.contains(floor))
						addUp(floor);
				}
			}else{
				if(moving == -1&&currentFloor<=floor){
					if(!nextDown.contains(floor))
						nextDown.add(floor);
				}
				else if(moving == 1&&currentFloor>=floor){
					if(!nextDown.contains(floor))
						nextDown.add(floor);
					}
				else
				{
					if(!downStops.contains(floor))
						addDown(floor);
				}
			}
		}
	}
	/**
	 * adds floor to the list of stops on the way down
	 * @param floor
	 */
	private void addDown(int floor){
		int size = downStops.size();
		if(!downStops.contains(floor)){
			for(int i = 0;i<size;i++){
				if(downStops.elementAt(i)>floor){
					continue;
				}
				downStops.insertElementAt(floor, i);
				break;
			}
			if(size == downStops.size()){
				downStops.add(floor);
			}
		}
	}
	/**
	 * adds floor to list of stops on the way up
	 * @param floor
	 */
	private void addUp(int floor){
		int size = upStops.size();
		if(!upStops.contains(floor)){
			for(int i = 0;i<size;i++){
				if(upStops.elementAt(i)<floor){
					continue;
				}
				upStops.insertElementAt(floor, i);
				break;
			}
			if(size == upStops.size()){
				upStops.add(floor);
			}
		}
	}
	/**
	 * returns the next floor the elevator should stop on
	 * 
	 */
	public int nextStop(){
		if(upStops.isEmpty()&&downStops.isEmpty()){
			return -1;
		}
		if(goingUp){
			if(upStops.isEmpty()){
				System.out.println("error up");
				return -2;
			}
			if(currentFloor<upStops.firstElement())
				moving = 1;
			else
				moving = -1;
			return upStops.firstElement();
		}else{
			if(downStops.isEmpty()){
				System.out.println("error down");
				return -2;
			}
			if(currentFloor<downStops.firstElement())
				moving = 1;
			else
				moving = -1;
			return downStops.firstElement();
		}
	}
	/**
	 * return true if the elevator algorithm has no data
	 * @return
	 */
	public boolean isIdle(){
		if(upStops.isEmpty()&&downStops.isEmpty())
			return true;
		return false;
	}
	/**
	 * returns true if the elevator is moving upwards
	 * @return
	 */
	public boolean movingUp(){
		return goingUp;
	}
	/**
	 * sets the current floor, should be set as soon as the elevator is at or past a floor 
	 * @param floor
	 */
	public void movingPast(int floor){
		currentFloor = floor;
		if(currentFloor<nextStop())
			moving = 1;
		else
			moving = -1;
	}
	
	/**
	 * Returns the current floor as a int. Could be tricky if called between to floors.
	 * Recommend to only use if the elevator is idle.
	 * @return
	 */
	public int getCurrentFloor(){
		return currentFloor;
	}
	
	public void clear(){
		upStops.clear();
		downStops.clear();
		nextDown.clear();
		nextUp.clear();
		moving = 0;
	}
	
	public void printInfo(){
		System.out.println("	CurrentFloor:" +currentFloor + ", goingUp:" +goingUp);
		if(upStops.size() > 0){
			System.out.print("	upStops:");
			for(int i: upStops){
				System.out.print(i+",");
			}
			System.out.println();
		}
		
		if(downStops.size() > 0){
			System.out.print("	downStops:");
			for(int i: downStops){
				System.out.print(i+",");
			}
			System.out.println();
		}
		
		if(nextUp.size() > 0){
			System.out.print("	nextUp:");
			for(int i: nextUp){
				System.out.print(i+",");
			}
			System.out.println();
		}
		
		if(nextDown.size() > 0){
			System.out.print("	nextDown:");
			for(int i: nextDown){
				System.out.print(i+",");
			}
			System.out.println();
		}
	}
}
